#include "interrupt_manager.h"
#include <stdlib.h>

//----------------------User Tools----------------------//
#ifdef HAL_UART_MODULE_ENABLED
// fputc重定向
int fputc(int ch, FILE *f)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
}
#endif /* HAL_UART_MODULE_ENABLED */

#ifdef HAL_CAN_MODULE_ENABLED
static CAN_TxHeaderTypeDef can_txheader;
static uint32_t can_txmailbox = 0;
// 把can的buf中的内容发送出去, 长度为8
void can_transmit(CAN_HandleTypeDef *hcan, uint16_t id, uint8_t *buf)
{

    if ((buf != NULL))
    {
        can_txheader.StdId = id;         /* 指定标准标识符，该值在0x00-0x7FF */
        can_txheader.IDE = CAN_ID_STD;   /* 指定将要传输消息的标识符类型 */
        can_txheader.RTR = CAN_RTR_DATA; /* 指定消息传输帧类型 */
        can_txheader.DLC = 8;            /* 指定将要传输的帧长度 */

        assert_param(HAL_CAN_AddTxMessage(hcan, &can_txheader, buf, &can_txmailbox) == HAL_OK);
    }
}
#endif /* HAL_CAN_MODULE_ENABLED */

//-----------------------------------------------Interrupt Manager---------------------------------------------------//

//--------------------------------------------------------------------------------------------------------------------
// GPIO Interrupt
#ifdef HAL_GPIO_MODULE_ENABLED
typedef struct
{
    uint16_t pin;
    void (*callback)(void);
} GPIO_Interrupt_t;
static uint8_t gpio_function_count = 0; // GPIO回调函数数量
static GPIO_Interrupt_t *gpio_it_array; // GPIO中断回调函数结构体数组
/**
 * 联接GPIO中断源和中断回调函数
 * 应输入GPIO引脚, 回调函数个数以及回调函数的地址
 * 联接后自动开启中断
 */
void attachinterrupt_gpio(uint16_t gpio_pin, void (*gpio_callback)(void))
{
    gpio_it_array = (GPIO_Interrupt_t *)realloc(gpio_it_array, (gpio_function_count + 1) * sizeof(GPIO_Interrupt_t));
    gpio_it_array[gpio_function_count].pin = gpio_pin;
    gpio_it_array[gpio_function_count].callback = gpio_callback;
    gpio_function_count++;
}
// GPIO中断回调
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    for (uint8_t i = 0; i < gpio_function_count; i++)
    {
        if (gpio_it_array[i].pin == GPIO_Pin)
        {
            gpio_it_array[i].callback();
        }
    }
}
#endif /* HAL_GPIO_MODULE_ENABLED */

//--------------------------------------------------------------------------------------------------------------------
// UART Interrupt
#ifdef HAL_UART_MODULE_ENABLED
typedef struct
{
    UART_HandleTypeDef *huart;
    uint8_t *rxbuf;
    uint8_t rxbuf_size;
    void (*callback)(uint8_t *pdata, uint8_t size);
} UART_Interrupt_t;
static uint8_t uart_function_count = 0; // UART回调函数数量
static UART_Interrupt_t *uart_it_array; // UART中断回调函数结构体数组
/**
 * 联接UART中断源和uart空闲中断回调函数
 * 应输入UART源, 回调函数个数以及回调函数的地址
 * 联接后自动开启中断
 */
void attachinterrupt_uart(UART_HandleTypeDef *huart, uint8_t buf_size, void (*uart_callback)(uint8_t *pdata, uint8_t size))
{
    uart_it_array = (UART_Interrupt_t *)realloc(uart_it_array, (uart_function_count + 1) * sizeof(UART_Interrupt_t));
    uart_it_array[uart_function_count].rxbuf_size = buf_size;
    uart_it_array[uart_function_count].rxbuf = (uint8_t *)malloc(buf_size * sizeof(uint8_t));
    uart_it_array[uart_function_count].huart = huart;
    uart_it_array[uart_function_count].callback = uart_callback;
    assert_param(HAL_UARTEx_ReceiveToIdle_IT(huart, uart_it_array[uart_function_count].rxbuf, buf_size) == HAL_OK);
    uart_function_count++;
}

// UART空闲中断回调
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    for (uint8_t i = 0; i < uart_function_count; i++)
    {
        if (uart_it_array[i].huart == huart)
        {
            uart_it_array[i].callback(uart_it_array[i].rxbuf, Size);
            assert_param(HAL_UARTEx_ReceiveToIdle_IT(huart, uart_it_array[i].rxbuf, uart_it_array[i].rxbuf_size) == HAL_OK);
        }
    }
}
typedef struct
{
    UART_HandleTypeDef *huart;
    uint8_t *rxbuf;
    uint8_t rxbuf_size;
    void (*callback)(void);
} UART_DMA_Interrupt_t;
static uint8_t uart_dma_function_count = 0;     // DMA回调函数数量
static UART_DMA_Interrupt_t *uart_dma_it_array; // UART中断回调函数结构体数组
/**
 * 联接UART DMA和中断回调函数
 * 应输入UART源, 回调函数个数以及回调函数的地址
 * 联接后自动开启DMA
 */
void attachinterrupt_uart_dma(UART_HandleTypeDef *huart, uint8_t *pbuf, uint8_t buf_size, void (*uart_callback)(void))
{
    uart_dma_it_array = (UART_DMA_Interrupt_t *)realloc(uart_dma_it_array, (uart_dma_function_count + 1) * sizeof(UART_DMA_Interrupt_t));
    uart_dma_it_array[uart_dma_function_count].huart = huart;
    uart_dma_it_array[uart_dma_function_count].rxbuf = pbuf;
    uart_dma_it_array[uart_dma_function_count].rxbuf_size = buf_size;
    uart_dma_it_array[uart_dma_function_count].callback = uart_callback;
    assert_param(HAL_UART_Receive_DMA(huart, pbuf, buf_size) == HAL_OK);
    uart_dma_function_count++;
}
// UART完成中断
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    for (uint8_t i = 0; i < uart_dma_function_count; i++)
    {
        if (uart_dma_it_array[i].huart == huart)
        {
            uart_dma_it_array[i].callback();
            assert_param(HAL_UART_Receive_DMA(huart, uart_dma_it_array[i].rxbuf, uart_dma_it_array[i].rxbuf_size) == HAL_OK);
        }
    }
}
#endif /* HAL_UART_MODULE_ENABLED */

//--------------------------------------------------------------------------------------------------------------------
// CAN Interrupt
#ifdef HAL_CAN_MODULE_ENABLED
typedef struct
{
    CAN_HandleTypeDef *hcan;
    void (*callback)(CAN_RxHeaderTypeDef *pheader, uint8_t *pdata);
} CAN_Interrupt_t;
static CAN_RxHeaderTypeDef can_rxheader;
static uint8_t can_rxbuf[8];
static uint8_t can_function_count = 0; // CAN回调函数数量
static CAN_Interrupt_t *can_it_array;  // CAN中断回调函数结构体数组
/**
 * CAN过滤器配置
 * 如果使用了AttachInterrupt_CAN函数则无需再使用
 */
void can_filterinit(CAN_HandleTypeDef *hcan)
{
    CAN_FilterTypeDef can_filter_structure;
    can_filter_structure.FilterActivation = ENABLE;
    can_filter_structure.FilterMode = CAN_FILTERMODE_IDMASK;
    can_filter_structure.FilterScale = CAN_FILTERSCALE_32BIT;
    can_filter_structure.FilterIdHigh = 0x0000;
    can_filter_structure.FilterIdLow = 0x0000;
    can_filter_structure.FilterMaskIdHigh = 0x0000;
    can_filter_structure.FilterMaskIdLow = 0x0000;
    can_filter_structure.FilterFIFOAssignment = CAN_RX_FIFO0;
    can_filter_structure.FilterBank = 0;
    HAL_CAN_ConfigFilter(hcan, &can_filter_structure);
    assert_param(HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING) == HAL_OK);
    assert_param(HAL_CAN_Start(hcan) == HAL_OK);
}
/**
 * 联接CAN中断源和中断回调函数
 * 应输入CAN源, 回调函数个数以及回调函数的地址
 * 联接后自动开启中断
 */
void attachinterrupt_can(CAN_HandleTypeDef *hcan, void (*can_callback)(CAN_RxHeaderTypeDef *pheader, uint8_t *pdata))
{
    can_it_array = (CAN_Interrupt_t *)realloc(can_it_array, (can_function_count + 1) * sizeof(CAN_Interrupt_t));
    can_it_array[can_function_count].hcan = hcan;
    can_it_array[can_function_count].callback = can_callback;
    can_function_count++;
}
// CAN中断回调
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    assert_param(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can_rxheader, can_rxbuf) == HAL_OK);

    for (uint8_t i = 0; i < can_function_count; i++)
    {
        if (can_it_array[i].hcan == hcan)
        {
            can_it_array[i].callback(&can_rxheader, can_rxbuf);
        }
    }
}
#endif /* HAL_CAN_MODULE_ENABLED */

//-------------------------------------------------------------------------------------------------------------------
// TIM Interrupt
#ifdef HAL_TIM_MODULE_ENABLED
typedef struct
{
    TIM_HandleTypeDef *htim;
    void (*callback)(void);
} TIM_Interrupt_t;
static uint8_t tim_function_count = 0; // TIM回调函数数量
static TIM_Interrupt_t *tim_it_array;  // TIM中断回调函数结构体数组指针
/**
 * 联接TIM中断源和中断回调函数
 * 应输入TIM源, 回调函数个数以及回调函数的地址
 * 联接后会自动开启中断
 */
void attachInterrupt_tim(TIM_HandleTypeDef *htim, void (*tim_callback)(void))
{
    tim_it_array = (TIM_Interrupt_t *)realloc(tim_it_array, (tim_function_count + 1) * sizeof(TIM_Interrupt_t));
    tim_it_array[tim_function_count].htim = htim;
    tim_it_array[tim_function_count].callback = tim_callback;
    tim_function_count++;
}
/**
 * TIM中断回调
 * 如果更改了系统时钟源，需要在main.c文件中的HAL_TIM_PeriodElapsedCallback()中调用此函数
 */
void tim_period_elapsed_callback(TIM_HandleTypeDef *htim)
{
    for (uint8_t i = 0; i < tim_function_count; i++)
    {
        if (tim_it_array[i].htim == htim)
        {
            tim_it_array[i].callback();
        }
    }
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    tim_period_elapsed_callback(htim);
}
#endif /* HAL_TIM_MODULE_ENABLED */
